寄存器1、怎么操作stm32寄存器/操作单片机寄存器 您所在的位置:网站首页 stm32 内核寄存器 寄存器1、怎么操作stm32寄存器/操作单片机寄存器

寄存器1、怎么操作stm32寄存器/操作单片机寄存器

2024-07-16 12:52| 来源: 网络整理| 查看: 265

学习单片机时经常听说学会操作寄存器很重要,情况也确实如此,比如某些功能库函数不能实现,或者库函数效率很低时,就只能直接操作寄存器实现。

通过3个问题就能理解寄存器及其操作。 什么是寄存器(就是个数字)?

简单可以理解为能够通过软件改写数值、控制硬件的一个32bit的数字。多个数字一起控制一个外设。

这个数值在哪?

这个数字要被存起来,就一定有一个存储的地址,地址可以通过单片机的数据手册查到。

如何改写这个数值?

 有了地址,可以设置一个指针指向此地址,然后写入数据。有库可以直接写寄存器名字进行操作。

详细解读: 1、什么是寄存器(就是个数字)?

寄存器是软件控制硬件的接口,几乎所有的硬件功能控制都是通过操作寄存器来实现的,库函数也只是将寄存器操作封装成函数,方便调用,一些复杂操作库函数可能无法实现,就只能直接操作寄存器。

一个寄存器32bit,按规则修改这个32bit数值就能控制硬件,通常一个外设需要多个寄存器控制。

2、这个数值在哪?

因为ARM单片机是统一编址的,寄存器像内存一样,内存中每个数据都有一个存储的地址,寄存器也是,只是寄存器的地址是固定的,你只能修改指定地址存储的数字才能控制硬件。

如何查找寄存器:以控制GPIO的寄存器为例。

(1)首先要有《stm32中文参考手册》这个网上很多,随便一搜就有。

(2)在目录中可以看到各种外设,比如下面这些有RCC、GPIO、DMA、ADC等

(3)展开目录,基本每一个外设的章节都有一个寄存器描述

(4)查看寄存器详细描述这一小节。

这里有三个关键点,了解这三点就知道改寄存器的规则了,如下图的①②③所示。

①偏移地址

这个寄存器叫CRL(全称应该是control register low),但具体地址并没有直接给出,而是以具体地址=基地址+偏移地址的形式计算的。其中基地址可以在2.3存储器映像这一章找到,如图:

         如果我们要控制GPIOA的CRL寄存器那么,CRL的地址就是0x40010800+0x00=0x40010800;在它后面的CRH寄存器偏移量为0x04,那么GPIOA的CRH地址为0x40010800+0x04=0x40010804;

手册里为什么要这样写?因为GPIO有多组,GPIOA、GPIOB。。。。每一组都有这个寄存器,且功能相同,只是位置不一样。

这样就比较方便在程序上的定义与使用,定义一个结构体,结构体数据形式和寄存器一样,只需要指定结构体基地址,就比较容易进行寄存器读写,而不用指定每个寄存器地址。

----------|----------|----------|----------|----------| GPIOA | GPIOB | GPIOx | GPIOF | .... | | ----------|----------|----------|----------|----------| | CRL | CRL | CRL | CRL | CRL | | ----------|----------|----------|----------|----------| | CRH | CRH | CRH | CRH | CRH | | ----------|----------|----------|----------|----------| | IDR | IDR | IDR | IDR | IDR | ↓ ----------|----------|----------|----------|----------| 地址4字节递增 ... | | | | | typedef struct { vu32 CRL; vu32 CRH; vu32 IDR; ... } GPIO_TypeDef;

②这两条方框是干嘛的

仔细看方框上有数字1-15和16-31这就是之前说的,每个寄存器是一个32bit数字。

1bit或几个bit组合在一起用于设置功能,比如③号框圈起来的30和31bit,这2bit一起决定一个功能。

③每bit数字具体功能

那么③里的2bit是什么功能,就要看下面的具体描述,这些描述功能的文字应该很熟悉了吧。

3、怎么修改这些寄存器

现在我们知道了这些寄存器的功能和地址,那么下一步就是修改它的数值了。做开发时我们主要还是使用固件库(只是掺杂一点直接修改寄存器操作),而库文件中定义了这些寄存器的地址,我们只需要通过他的名字访问他就行。

就比如上图中的GPIOx_CRL,这是一个通用名,比如要控制GPIOA的这个寄存器那么具体操作如下

GPIOA->CRL = 0x44444444;

 其实操作寄存器并不难,难点是了解每个外设各个寄存器的作用。要完全了解一个外设的寄存器,可以通过寄存器例程和手册中的寄存器描述,结合实践加深对外设控制的理解。

扩展:

1、stm32固件库库是如何实通过寄存器名字操作寄存器的?

要理解这个问题需要有良好的C语言基础,理解起来还是比较简单的。

每一组控制GPIO的几个寄存器地址是连续的,按4字节递增(每个寄存器占4字节)。

那么我们只需要定义一个结构体,成员变量都定义为32位无符号整形变量,成员的数量就是寄存器的数量。以GPIO为例

typedef struct { __IO uint32_t CRL; __IO uint32_t CRH; __IO uint32_t IDR; __IO uint32_t ODR; __IO uint32_t BSRR; __IO uint32_t BRR; __IO uint32_t LCKR; } GPIO_TypeDef; GPIO_TypeDef *GPIOA; GPIOA = GPIOA的基地址; GPIOA->ODR = 0x11114444; 通过GPIOA这个指针访问对应的寄存器地址。 编译器会自动计算ODR相对GPIOA基地址的具体地址。

2、一些给寄存器赋值的小技巧。

通常我们只想修改32bit中的某一位,清零或者置1

GPIOA->CRL |= 1


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有